﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Pg.BioMedics.SDR.Entities;

namespace Pg.BioMedics.SDR.Services.Algorithms
{
    /// <summary>
    /// Implementation of cosine toerm based RSV value calculation method
    /// </summary>
    internal class RSVCosineAlgorithm : IRSVAlgorithm
    {
        #region Fields

        private IWeightingAlgorithm weighthingAlgorithm;

        #endregion

        #region Constructors

        /// <summary>
        /// Creates instance of cosine based RSV calculation algorithm 
        /// </summary>
        /// <param name="weighthingAlgorithm">Weighting algortihm</param>
        internal RSVCosineAlgorithm(IWeightingAlgorithm weighthingAlgorithm)
        {
            this.weighthingAlgorithm = weighthingAlgorithm;
        }

        #endregion

        #region IRSVAlgorithm Members

        /// <summary>
        /// Calculates relevance score between query terms vector Q and document terms vector D
        /// </summary>
        /// <param name="Q">Query terms vector</param>
        /// <param name="D">Document terms vector</param>
        /// <returns>Relevance score between compared vectors</returns>
        public double Calculate(Token[] Q, Token[] D)
        {
            double rsv = 0.0d;
            SortedList<string, Token> queryTokens = new SortedList<string,Token>();
            foreach (Token t in Q)
            {
                rsv += this.weighthingAlgorithm.CalculateQWeight(t, Q) * this.weighthingAlgorithm.CalculateDWeight(t, D);
                queryTokens.Add(t.Value, t);
            }

            foreach (Token t in D)
                if (!queryTokens.ContainsKey(t.Value))
                    rsv += this.weighthingAlgorithm.CalculateQWeight(t, Q) * this.weighthingAlgorithm.CalculateDWeight(t, D);

            return rsv;
        }

        #endregion
    }
}
